home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / AvantBrowser / asetup.exe / _data / webkit / resources.pak / Unnamed File 000083.txt < prev    next >
Text File  |  2013-04-03  |  18KB  |  677 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. cr.define('cr.ui', function() {
  6.   // require cr.ui.define
  7.   // require cr.ui.limitInputWidth
  8.  
  9.   /**
  10.    * The number of pixels to indent per level.
  11.    * @type {number}
  12.    * @const
  13.    */
  14.   var INDENT = 20;
  15.  
  16.   /**
  17.    * Returns the computed style for an element.
  18.    * @param {!Element} el The element to get the computed style for.
  19.    * @return {!CSSStyleDeclaration} The computed style.
  20.    */
  21.   function getComputedStyle(el) {
  22.     return el.ownerDocument.defaultView.getComputedStyle(el);
  23.   }
  24.  
  25.   /**
  26.    * Helper function that finds the first ancestor tree item.
  27.    * @param {!Element} el The element to start searching from.
  28.    * @return {cr.ui.TreeItem} The found tree item or null if not found.
  29.    */
  30.   function findTreeItem(el) {
  31.     while (el && !(el instanceof TreeItem)) {
  32.       el = el.parentNode;
  33.     }
  34.     return el;
  35.   }
  36.  
  37.   /**
  38.    * Creates a new tree element.
  39.    * @param {Object=} opt_propertyBag Optional properties.
  40.    * @constructor
  41.    * @extends {HTMLElement}
  42.    */
  43.   var Tree = cr.ui.define('tree');
  44.  
  45.   Tree.prototype = {
  46.     __proto__: HTMLElement.prototype,
  47.  
  48.     /**
  49.      * Initializes the element.
  50.      */
  51.     decorate: function() {
  52.       // Make list focusable
  53.       if (!this.hasAttribute('tabindex'))
  54.         this.tabIndex = 0;
  55.  
  56.       this.addEventListener('click', this.handleClick);
  57.       this.addEventListener('mousedown', this.handleMouseDown);
  58.       this.addEventListener('dblclick', this.handleDblClick);
  59.       this.addEventListener('keydown', this.handleKeyDown);
  60.     },
  61.  
  62.     /**
  63.      * Returns the tree item that are children of this tree.
  64.      */
  65.     get items() {
  66.       return this.children;
  67.     },
  68.  
  69.     /**
  70.      * Adds a tree item to the tree.
  71.      * @param {!cr.ui.TreeItem} treeItem The item to add.
  72.      */
  73.     add: function(treeItem) {
  74.       this.addAt(treeItem, 0xffffffff);
  75.     },
  76.  
  77.     /**
  78.      * Adds a tree item at the given index.
  79.      * @param {!cr.ui.TreeItem} treeItem The item to add.
  80.      * @param {number} index The index where we want to add the item.
  81.      */
  82.     addAt: function(treeItem, index) {
  83.       this.insertBefore(treeItem, this.children[index]);
  84.       treeItem.setDepth_(this.depth + 1);
  85.     },
  86.  
  87.     /**
  88.      * Removes a tree item child.
  89.      * @param {!cr.ui.TreeItem} treeItem The tree item to remove.
  90.      */
  91.     remove: function(treeItem) {
  92.       this.removeChild(treeItem);
  93.     },
  94.  
  95.     /**
  96.      * The depth of the node. This is 0 for the tree itself.
  97.      * @type {number}
  98.      */
  99.     get depth() {
  100.       return 0;
  101.     },
  102.  
  103.     /**
  104.      * Handles click events on the tree and forwards the event to the relevant
  105.      * tree items as necesary.
  106.      * @param {Event} e The click event object.
  107.      */
  108.     handleClick: function(e) {
  109.       var treeItem = findTreeItem(e.target);
  110.       if (treeItem)
  111.         treeItem.handleClick(e);
  112.     },
  113.  
  114.     handleMouseDown: function(e) {
  115.       if (e.button == 2) // right
  116.         this.handleClick(e);
  117.     },
  118.  
  119.     /**
  120.      * Handles double click events on the tree.
  121.      * @param {Event} e The dblclick event object.
  122.      */
  123.     handleDblClick: function(e) {
  124.       var treeItem = findTreeItem(e.target);
  125.       if (treeItem)
  126.         treeItem.expanded = !treeItem.expanded;
  127.     },
  128.  
  129.     /**
  130.      * Handles keydown events on the tree and updates selection and exanding
  131.      * of tree items.
  132.      * @param {Event} e The click event object.
  133.      */
  134.     handleKeyDown: function(e) {
  135.       var itemToSelect;
  136.       if (e.ctrlKey)
  137.         return;
  138.  
  139.       var item = this.selectedItem;
  140.  
  141.       var rtl = getComputedStyle(item).direction == 'rtl';
  142.  
  143.       switch (e.keyIdentifier) {
  144.         case 'Up':
  145.           itemToSelect = item ? getPrevious(item) :
  146.               this.items[this.items.length - 1];
  147.           break;
  148.         case 'Down':
  149.           itemToSelect = item ? getNext(item) :
  150.               this.items[0];
  151.           break;
  152.         case 'Left':
  153.         case 'Right':
  154.           // Don't let back/forward keyboard shortcuts be used.
  155.           if (!cr.isMac && e.altKey || cr.isMac && e.metaKey)
  156.             break;
  157.  
  158.           if (e.keyIdentifier == 'Left' && !rtl ||
  159.               e.keyIdentifier == 'Right' && rtl) {
  160.             if (item.expanded)
  161.               item.expanded = false;
  162.             else
  163.               itemToSelect = findTreeItem(item.parentNode);
  164.           } else {
  165.             if (!item.expanded)
  166.               item.expanded = true;
  167.             else
  168.               itemToSelect = item.items[0];
  169.           }
  170.           break;
  171.         case 'Home':
  172.           itemToSelect = this.items[0];
  173.           break;
  174.         case 'End':
  175.           itemToSelect = this.items[this.items.length - 1];
  176.           break;
  177.       }
  178.  
  179.       if (itemToSelect) {
  180.         itemToSelect.selected = true;
  181.         e.preventDefault();
  182.       }
  183.     },
  184.  
  185.     /**
  186.      * The selected tree item or null if none.
  187.      * @type {cr.ui.TreeItem}
  188.      */
  189.     get selectedItem() {
  190.       return this.selectedItem_ || null;
  191.     },
  192.     set selectedItem(item) {
  193.       var oldSelectedItem = this.selectedItem_;
  194.       if (oldSelectedItem != item) {
  195.         // Set the selectedItem_ before deselecting the old item since we only
  196.         // want one change when moving between items.
  197.         this.selectedItem_ = item;
  198.  
  199.         if (oldSelectedItem)
  200.           oldSelectedItem.selected = false;
  201.  
  202.         if (item)
  203.           item.selected = true;
  204.  
  205.         cr.dispatchSimpleEvent(this, 'change');
  206.       }
  207.     },
  208.  
  209.     /**
  210.      * @return {!ClientRect} The rect to use for the context menu.
  211.      */
  212.     getRectForContextMenu: function() {
  213.       // TODO(arv): Add trait support so we can share more code between trees
  214.       // and lists.
  215.       if (this.selectedItem)
  216.         return this.selectedItem.rowElement.getBoundingClientRect();
  217.       return this.getBoundingClientRect();
  218.     }
  219.   };
  220.  
  221.   /**
  222.    * Determines the visibility of icons next to the treeItem labels. If set to
  223.    * 'hidden', no space is reserved for icons and no icons are displayed next
  224.    * to treeItem labels. If set to 'parent', folder icons will be displayed
  225.    * next to expandable parent nodes. If set to 'all' folder icons will be
  226.    * displayed next to all nodes. Icons can be set using the treeItem's icon
  227.    * property.
  228.    */
  229.   cr.defineProperty(Tree, 'iconVisibility', cr.PropertyKind.ATTR);
  230.  
  231.   /**
  232.    * This is used as a blueprint for new tree item elements.
  233.    * @type {!HTMLElement}
  234.    */
  235.   var treeItemProto = (function() {
  236.     var treeItem = cr.doc.createElement('div');
  237.     treeItem.className = 'tree-item';
  238.     treeItem.innerHTML = '<div class=tree-row>' +
  239.         '<span class=expand-icon></span>' +
  240.         '<span class=tree-label></span>' +
  241.         '</div>' +
  242.         '<div class=tree-children></div>';
  243.     treeItem.setAttribute('role', 'treeitem');
  244.     return treeItem;
  245.   })();
  246.  
  247.   /**
  248.    * Creates a new tree item.
  249.    * @param {Object=} opt_propertyBag Optional properties.
  250.    * @constructor
  251.    * @extends {HTMLElement}
  252.    */
  253.   var TreeItem = cr.ui.define(function() {
  254.     return treeItemProto.cloneNode(true);
  255.   });
  256.  
  257.   TreeItem.prototype = {
  258.     __proto__: HTMLElement.prototype,
  259.  
  260.     /**
  261.      * Initializes the element.
  262.      */
  263.     decorate: function() {
  264.  
  265.     },
  266.  
  267.     /**
  268.      * The tree items children.
  269.      */
  270.     get items() {
  271.       return this.lastElementChild.children;
  272.     },
  273.  
  274.     /**
  275.      * The depth of the tree item.
  276.      * @type {number}
  277.      */
  278.     depth_: 0,
  279.     get depth() {
  280.       return this.depth_;
  281.     },
  282.  
  283.     /**
  284.      * Sets the depth.
  285.      * @param {number} depth The new depth.
  286.      * @private
  287.      */
  288.     setDepth_: function(depth) {
  289.       if (depth != this.depth_) {
  290.         this.rowElement.style.WebkitPaddingStart = Math.max(0, depth - 1) *
  291.             INDENT + 'px';
  292.         this.depth_ = depth;
  293.         var items = this.items;
  294.         for (var i = 0, item; item = items[i]; i++) {
  295.           item.setDepth_(depth + 1);
  296.         }
  297.       }
  298.     },
  299.  
  300.     /**
  301.      * Adds a tree item as a child.
  302.      * @param {!cr.ui.TreeItem} child The child to add.
  303.      */
  304.     add: function(child) {
  305.       this.addAt(child, 0xffffffff);
  306.     },
  307.  
  308.     /**
  309.      * Adds a tree item as a child at a given index.
  310.      * @param {!cr.ui.TreeItem} child The child to add.
  311.      * @param {number} index The index where to add the child.
  312.      */
  313.     addAt: function(child, index) {
  314.       this.lastElementChild.insertBefore(child, this.items[index]);
  315.       if (this.items.length == 1)
  316.         this.hasChildren = true;
  317.       child.setDepth_(this.depth + 1);
  318.     },
  319.  
  320.     /**
  321.      * Removes a child.
  322.      * @param {!cr.ui.TreeItem} child The tree item child to remove.
  323.      */
  324.     remove: function(child) {
  325.       // If we removed the selected item we should become selected.
  326.       var tree = this.tree;
  327.       var selectedItem = tree.selectedItem;
  328.       if (selectedItem && child.contains(selectedItem))
  329.         this.selected = true;
  330.  
  331.       this.lastElementChild.removeChild(child);
  332.       if (this.items.length == 0)
  333.         this.hasChildren = false;
  334.     },
  335.  
  336.     /**
  337.      * The parent tree item.
  338.      * @type {!cr.ui.Tree|cr.ui.TreeItem}
  339.      */
  340.     get parentItem() {
  341.       var p = this.parentNode;
  342.       while (p && !(p instanceof TreeItem) && !(p instanceof Tree)) {
  343.         p = p.parentNode;
  344.       }
  345.       return p;
  346.     },
  347.  
  348.     /**
  349.      * The tree that the tree item belongs to or null of no added to a tree.
  350.      * @type {cr.ui.Tree}
  351.      */
  352.     get tree() {
  353.       var t = this.parentItem;
  354.       while (t && !(t instanceof Tree)) {
  355.         t = t.parentItem;
  356.       }
  357.       return t;
  358.     },
  359.  
  360.     /**
  361.      * Whether the tree item is expanded or not.
  362.      * @type {boolean}
  363.      */
  364.     get expanded() {
  365.       return this.hasAttribute('expanded');
  366.     },
  367.     set expanded(b) {
  368.       if (this.expanded == b)
  369.         return;
  370.  
  371.       var treeChildren = this.lastElementChild;
  372.  
  373.       if (b) {
  374.         if (this.mayHaveChildren_) {
  375.           this.setAttribute('expanded', '');
  376.           treeChildren.setAttribute('expanded', '');
  377.           cr.dispatchSimpleEvent(this, 'expand', true);
  378.           this.scrollIntoViewIfNeeded(false);
  379.         }
  380.       } else {
  381.         var tree = this.tree;
  382.         if (tree && !this.selected) {
  383.           var oldSelected = tree.selectedItem;
  384.           if (oldSelected && this.contains(oldSelected))
  385.             this.selected = true;
  386.         }
  387.         this.removeAttribute('expanded');
  388.         treeChildren.removeAttribute('expanded');
  389.         cr.dispatchSimpleEvent(this, 'collapse', true);
  390.       }
  391.     },
  392.  
  393.     /**
  394.      * Expands all parent items.
  395.      */
  396.     reveal: function() {
  397.       var pi = this.parentItem;
  398.       while (pi && !(pi instanceof Tree)) {
  399.         pi.expanded = true;
  400.         pi = pi.parentItem;
  401.       }
  402.     },
  403.  
  404.     /**
  405.      * The element representing the row that gets highlighted.
  406.      * @type {!HTMLElement}
  407.      */
  408.     get rowElement() {
  409.       return this.firstElementChild;
  410.     },
  411.  
  412.     /**
  413.      * The element containing the label text and the icon.
  414.      * @type {!HTMLElement}
  415.      */
  416.     get labelElement() {
  417.       return this.firstElementChild.lastElementChild;
  418.     },
  419.  
  420.     /**
  421.      * The label text.
  422.      * @type {string}
  423.      */
  424.     get label() {
  425.       return this.labelElement.textContent;
  426.     },
  427.     set label(s) {
  428.       this.labelElement.textContent = s;
  429.     },
  430.  
  431.     /**
  432.      * The URL for the icon.
  433.      * @type {string}
  434.      */
  435.     get icon() {
  436.       return getComputedStyle(this.labelElement).backgroundImage.slice(4, -1);
  437.     },
  438.     set icon(icon) {
  439.       return this.labelElement.style.backgroundImage = url(icon);
  440.     },
  441.  
  442.     /**
  443.      * Whether the tree item is selected or not.
  444.      * @type {boolean}
  445.      */
  446.     get selected() {
  447.       return this.hasAttribute('selected');
  448.     },
  449.     set selected(b) {
  450.       if (this.selected == b)
  451.         return;
  452.       var rowItem = this.firstElementChild;
  453.       var tree = this.tree;
  454.       if (b) {
  455.         this.setAttribute('selected', '');
  456.         rowItem.setAttribute('selected', '');
  457.         this.reveal();
  458.         this.labelElement.scrollIntoViewIfNeeded(false);
  459.         if (tree)
  460.           tree.selectedItem = this;
  461.       } else {
  462.         this.removeAttribute('selected');
  463.         rowItem.removeAttribute('selected');
  464.         if (tree && tree.selectedItem == this)
  465.           tree.selectedItem = null;
  466.       }
  467.     },
  468.  
  469.     /**
  470.      * Whether the tree item has children.
  471.      * @type {boolean}
  472.      */
  473.     get mayHaveChildren_() {
  474.       return this.hasAttribute('may-have-children');
  475.     },
  476.     set mayHaveChildren_(b) {
  477.       var rowItem = this.firstElementChild;
  478.       if (b) {
  479.         this.setAttribute('may-have-children', '');
  480.         rowItem.setAttribute('may-have-children', '');
  481.       } else {
  482.         this.removeAttribute('may-have-children');
  483.         rowItem.removeAttribute('may-have-children');
  484.       }
  485.     },
  486.  
  487.     /**
  488.      * Whether the tree item has children.
  489.      * @type {boolean}
  490.      */
  491.     get hasChildren() {
  492.       return !!this.items[0];
  493.     },
  494.  
  495.     /**
  496.      * Whether the tree item has children.
  497.      * @type {boolean}
  498.      */
  499.     set hasChildren(b) {
  500.       var rowItem = this.firstElementChild;
  501.       this.setAttribute('has-children', b);
  502.       rowItem.setAttribute('has-children', b);
  503.       if (b)
  504.         this.mayHaveChildren_ = true;
  505.     },
  506.  
  507.     /**
  508.      * Called when the user clicks on a tree item. This is forwarded from the
  509.      * cr.ui.Tree.
  510.      * @param {Event} e The click event.
  511.      */
  512.     handleClick: function(e) {
  513.       if (e.target.className == 'expand-icon')
  514.         this.expanded = !this.expanded;
  515.       else
  516.         this.selected = true;
  517.     },
  518.  
  519.     /**
  520.      * Makes the tree item user editable. If the user renamed the item a
  521.      * bubbling {@code rename} event is fired.
  522.      * @type {boolean}
  523.      */
  524.     set editing(editing) {
  525.       var oldEditing = this.editing;
  526.       if (editing == oldEditing)
  527.         return;
  528.  
  529.       var self = this;
  530.       var labelEl = this.labelElement;
  531.       var text = this.label;
  532.       var input;
  533.  
  534.       // Handles enter and escape which trigger reset and commit respectively.
  535.       function handleKeydown(e) {
  536.         // Make sure that the tree does not handle the key.
  537.         e.stopPropagation();
  538.  
  539.         // Calling tree.focus blurs the input which will make the tree item
  540.         // non editable.
  541.         switch (e.keyIdentifier) {
  542.           case 'U+001B':  // Esc
  543.             input.value = text;
  544.             // fall through
  545.           case 'Enter':
  546.             self.tree.focus();
  547.         }
  548.       }
  549.  
  550.       function stopPropagation(e) {
  551.         e.stopPropagation();
  552.       }
  553.  
  554.       if (editing) {
  555.         this.selected = true;
  556.         this.setAttribute('editing', '');
  557.         this.draggable = false;
  558.  
  559.         // We create an input[type=text] and copy over the label value. When
  560.         // the input loses focus we set editing to false again.
  561.         input = this.ownerDocument.createElement('input');
  562.         input.value = text;
  563.         if (labelEl.firstChild)
  564.           labelEl.replaceChild(input, labelEl.firstChild);
  565.         else
  566.           labelEl.appendChild(input);
  567.  
  568.         input.addEventListener('keydown', handleKeydown);
  569.         input.addEventListener('blur', (function() {
  570.           this.editing = false;
  571.         }).bind(this));
  572.  
  573.         // Make sure that double clicks do not expand and collapse the tree
  574.         // item.
  575.         var eventsToStop = ['mousedown', 'mouseup', 'contextmenu', 'dblclick'];
  576.         eventsToStop.forEach(function(type) {
  577.           input.addEventListener(type, stopPropagation);
  578.         });
  579.  
  580.         // Wait for the input element to recieve focus before sizing it.
  581.         var rowElement = this.rowElement;
  582.         function onFocus() {
  583.           input.removeEventListener('focus', onFocus);
  584.           // 20 = the padding and border of the tree-row
  585.           cr.ui.limitInputWidth(input, rowElement, 100);
  586.         }
  587.         input.addEventListener('focus', onFocus);
  588.         input.focus();
  589.         input.select();
  590.  
  591.         this.oldLabel_ = text;
  592.       } else {
  593.         this.removeAttribute('editing');
  594.         this.draggable = true;
  595.         input = labelEl.firstChild;
  596.         var value = input.value;
  597.         if (/^\s*$/.test(value)) {
  598.           labelEl.textContent = this.oldLabel_;
  599.         } else {
  600.           labelEl.textContent = value;
  601.           if (value != this.oldLabel_) {
  602.             cr.dispatchSimpleEvent(this, 'rename', true);
  603.           }
  604.         }
  605.         delete this.oldLabel_;
  606.       }
  607.     },
  608.  
  609.     get editing() {
  610.       return this.hasAttribute('editing');
  611.     }
  612.   };
  613.  
  614.   /**
  615.    * Helper function that returns the next visible tree item.
  616.    * @param {cr.ui.TreeItem} item The tree item.
  617.    * @return {cr.ui.TreeItem} The found item or null.
  618.    */
  619.   function getNext(item) {
  620.     if (item.expanded) {
  621.       var firstChild = item.items[0];
  622.       if (firstChild) {
  623.         return firstChild;
  624.       }
  625.     }
  626.  
  627.     return getNextHelper(item);
  628.   }
  629.  
  630.   /**
  631.    * Another helper function that returns the next visible tree item.
  632.    * @param {cr.ui.TreeItem} item The tree item.
  633.    * @return {cr.ui.TreeItem} The found item or null.
  634.    */
  635.   function getNextHelper(item) {
  636.     if (!item)
  637.       return null;
  638.  
  639.     var nextSibling = item.nextElementSibling;
  640.     if (nextSibling) {
  641.       return nextSibling;
  642.     }
  643.     return getNextHelper(item.parentItem);
  644.   }
  645.  
  646.   /**
  647.    * Helper function that returns the previous visible tree item.
  648.    * @param {cr.ui.TreeItem} item The tree item.
  649.    * @return {cr.ui.TreeItem} The found item or null.
  650.    */
  651.   function getPrevious(item) {
  652.     var previousSibling = item.previousElementSibling;
  653.     return previousSibling ? getLastHelper(previousSibling) : item.parentItem;
  654.   }
  655.  
  656.   /**
  657.    * Helper function that returns the last visible tree item in the subtree.
  658.    * @param {cr.ui.TreeItem} item The item to find the last visible item for.
  659.    * @return {cr.ui.TreeItem} The found item or null.
  660.    */
  661.   function getLastHelper(item) {
  662.     if (!item)
  663.       return null;
  664.     if (item.expanded && item.hasChildren) {
  665.       var lastChild = item.items[item.items.length - 1];
  666.       return getLastHelper(lastChild);
  667.     }
  668.     return item;
  669.   }
  670.  
  671.   // Export
  672.   return {
  673.     Tree: Tree,
  674.     TreeItem: TreeItem
  675.   };
  676. });
  677.